package com.fowo.api.syncAmazon.api;

import cn.hutool.core.date.DateUtil;
import com.amazon.spapi.api.ReportsApi;
import com.amazon.spapi.model.reports.CreateReportSpecification;
import com.amazon.spapi.model.reports.Report;
import com.amazon.spapi.model.reports.ReportDocument;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fowo.api.datainterface.entity.DatainterfaceAuthority;
import com.fowo.api.datainterface.service.DatainterfaceAuthorityService;
import com.fowo.api.entity.ListingFather;
import com.fowo.api.entity.ShopInfo;
import com.fowo.api.entity.TmpReimbursements;
import com.fowo.api.entity.TmpStorageFeeMonth;
import com.fowo.api.mapper.ListingFatherMapper;
import com.fowo.api.service.impl.ShopInfoServiceImpl;
import com.fowo.api.service.impl.TmpStorageFeeMonthServiceImpl;
import com.fowo.api.syncAmazon.util.AmazonUtil;
import com.fowo.api.syncAmazon.util.AmzDateUtils;
import com.fowo.api.syncAmazon.util.GeneralUtil;
import com.squareup.okhttp.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.*;
import java.util.zip.GZIPInputStream;

@Component
@Slf4j
public class StorageFeeMonthReportService extends ReportService {
    @Resource
    private DatainterfaceAuthorityService datainterfaceAuthorityBaseService;
    @Resource
    private AmazonUtil amazonUtil;
    @Resource
    private ShopInfoServiceImpl shopInfoService;
    @Resource
    private TmpStorageFeeMonthServiceImpl tmpStorageFeeMonthService;
    @Resource
    private ListingFatherMapper listingFatherMapper;

    /**
     * 月仓储费 数据
     * @throws Exception
     */
    public void getStorageFeeMonth() throws Exception {
        DatainterfaceAuthority entityAuthority = datainterfaceAuthorityBaseService.getOne(Wrappers.<DatainterfaceAuthority>lambdaQuery().eq(DatainterfaceAuthority::getAppCode,"Amazon"), false);

        final List<ShopInfo> list = shopInfoService.list(Wrappers.lambdaQuery(ShopInfo.class)
                .eq(ShopInfo::getPlatform,"Amazon")
                .eq(ShopInfo::getSellerAuthStatus,"SQ01"));
        for(ShopInfo shop : list){

            List<String> marketplaceIds = Arrays.asList(shop.getMarketplaceId().split(","));

            CreateReportSpecification body = new CreateReportSpecification();
            body.setReportType("GET_FBA_STORAGE_FEE_CHARGES_DATA");
            body.setMarketplaceIds(marketplaceIds);

            body.setDataStartTime(AmzDateUtils.getOffsetDateTimeUTC(DateUtil.beginOfMonth(DateUtil.lastMonth())));
            body.setDataEndTime(AmzDateUtils.getOffsetDateTimeUTC(DateUtil.endOfMonth(DateUtil.lastMonth())));

//            Calendar now = Calendar.getInstance();
//            Calendar cstart = GeneralUtil.getLastDayOfMonth(now.get(Calendar.YEAR),now.get(Calendar.MONTH)-2);
//            body.setDataStartTime(AmzDateUtils.getOffsetDateTimeUTC(cstart));
//            Calendar cend = GeneralUtil.getLastDayOfMonth(now.get(Calendar.YEAR),now.get(Calendar.MONTH)-1);
//            body.setDataEndTime(AmzDateUtils.getOffsetDateTimeUTC(cend));

            // 第一步 创建报告
            ReportsApi reportsApi = amazonUtil.getReportsApi(entityAuthority,shop,0.0167);
            final String reportId = createReport(reportsApi, body);
            // 第二步 检验报告是否完成
            ReportsApi reportsApi2 = amazonUtil.getReportsApi(entityAuthority,shop,2.0);
            final Report report = getReport(reportsApi2, reportId);
            // 第三步 获取报告连接
            ReportsApi reportsApi3 = amazonUtil.getReportsApi(entityAuthority,shop,0.0167);
            final ReportDocument reportDocument = reportsApi3.getReportDocument(report.getReportDocumentId());
            // 第四步 下载报告
            String compressionAlgorithm = null;
            if(null != reportDocument.getCompressionAlgorithm()){
                compressionAlgorithm = reportDocument.getCompressionAlgorithm().getValue();
            }
            download(reportDocument.getUrl(),compressionAlgorithm,shop);

        }
    }

    @Override
    public void download(String url, String compressionAlgorithm, ShopInfo shop) throws IOException, IllegalArgumentException {
        OkHttpClient httpclient = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        Response response = httpclient.newCall(request).execute();
        if (!response.isSuccessful()) {
            System.out.println(
                    String.format("Call to download content was unsuccessful with response code: %d and message: %s",
                            response.code(), response.message()));
            return;
        }

        try (ResponseBody responseBody = response.body()) {
            MediaType mediaType = MediaType.parse(response.header("Content-Type"));
            Charset charset = mediaType.charset();
            if (charset == null) {
                throw new IllegalArgumentException(String.format(
                        "Could not parse character set from '%s'", mediaType.toString()));
            }

            Closeable closeThis = null;
            try {
                InputStream inputStream = responseBody.byteStream();
                closeThis = inputStream;

                if ("GZIP".equals(compressionAlgorithm)) {
                    inputStream = new GZIPInputStream(inputStream);
                    closeThis = inputStream;
                }

                // This example assumes that the download content has a charset in the content-type header, e.g.
                // text/plain; charset=UTF-8
                if ("text".equals(mediaType.type()) && "plain".equals(mediaType.subtype())) {
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charset);
                    closeThis = inputStreamReader;

                    BufferedReader reader = new BufferedReader(inputStreamReader);
                    closeThis = reader;

                    int lineNumber = 0;
                    String line;
                    Map<String,Integer> titleList = new HashMap<String,Integer>();
                    List<TmpStorageFeeMonth> list = new ArrayList<>();
                    final List<ListingFather> listingFathers = listingFatherMapper.selectList(Wrappers.lambdaQuery(ListingFather.class).eq(ListingFather::getShop, shop.getId()));
                    while ((line = reader.readLine()) != null) {
                        String[] info = line.split("\t");
                        int length = info.length;
                        if (lineNumber == 0) {
                            for (int i = 0; i < length; i++) {
                                titleList.put(info[i],i);
                            }
                        } else {
                            TmpStorageFeeMonth tmp = new TmpStorageFeeMonth();
                            tmp.setCreateTime(new Date());
                            String asin= GeneralUtil.getStrValue(info, titleList, "asin");
                            String fnsku= GeneralUtil.getStrValue(info, titleList, "fnsku");
                            String product_name= GeneralUtil.getStrValue(info, titleList, "product_name");
                            String fulfillment_center= GeneralUtil.getStrValue(info, titleList, "fulfillment_center");
                            String country_code= GeneralUtil.getStrValue(info, titleList, "country_code");
                            String longest_side= GeneralUtil.getStrValue(info, titleList, "longest_side");
                            String median_side = GeneralUtil.getStrValue(info, titleList, "median_side");
                            String shortest_side= GeneralUtil.getStrValue(info, titleList, "shortest_side");
                            String measurement_units = GeneralUtil.getStrValue(info, titleList, "measurement_units");
                            String weight= GeneralUtil.getStrValue(info, titleList, "weight");
                            String weight_units= GeneralUtil.getStrValue(info, titleList, "weight_units");
                            String item_volume= GeneralUtil.getStrValue(info, titleList, "item_volume");
                            String volume_units= GeneralUtil.getStrValue(info, titleList, "volume_units");
                            String product_size_tier= GeneralUtil.getStrValue(info, titleList, "product_size_tier");//product_size_tier
                            BigDecimal average_quantity_on_hand= GeneralUtil.getBigDecimalValue(info, titleList, "average_quantity_on_hand");
                            BigDecimal average_quantity_pending_removal= GeneralUtil.getBigDecimalValue(info, titleList, "average_quantity_pending_removal");
                            BigDecimal estimated_total_item_volume= GeneralUtil.getBigDecimalValue(info, titleList, "estimated_total_item_volume");
                            String month_of_charge= GeneralUtil.getStrValue(info, titleList, "month_of_charge");
                            BigDecimal storage_rate= GeneralUtil.getBigDecimalValue(info, titleList, "storage_rate");
                            String currency= GeneralUtil.getStrValue(info, titleList, "currency");
                            BigDecimal estimated_monthly_storage_fee= GeneralUtil.getBigDecimalValue(info, titleList, "estimated_monthly_storage_fee");
                            String dangerous_goods_storage_type= GeneralUtil.getStrValue(info, titleList, "dangerous_goods_storage_type");
                            String eligible_for_inventory_discount= GeneralUtil.getStrValue(info, titleList, "eligible_for_inventory_discount");
                            String qualifies_for_inventory_discount= GeneralUtil.getStrValue(info, titleList, "qualifies_for_inventory_discount");
                            String total_incentive_fee_amount= GeneralUtil.getStrValue(info, titleList, "total_incentive_fee_amount");
                            String breakdown_incentive_fee_amount= GeneralUtil.getStrValue(info, titleList, "breakdown_incentive_fee_amount");
                            String average_quantity_customer_orders= GeneralUtil.getStrValue(info, titleList, "average_quantity_customer_orders");

                            final ListingFather listingFather = listingFathers.stream().filter(l -> l.getShop().equals(shop.getId()) && l.getFnsku().equals(fnsku) && l.getAsin().equals(asin)).findAny().orElse(new ListingFather());

                            tmp.setSid(shop.getId());
                            tmp.setImg(listingFather.getImg());
                            tmp.setName(listingFather.getProductName());
                            tmp.setSku(listingFather.getSku());
                            tmp.setCountry(shop.getMid());

                            tmp.setAsin(asin);
                            tmp.setFnsku(fnsku);
                            tmp.setProductName(product_name);
                            tmp.setFulfillmentCenter(fulfillment_center);
                            tmp.setCountryCode(country_code);
                            tmp.setLongestSide(longest_side);
                            tmp.setMedianSide(median_side);
                            tmp.setShortestSide(shortest_side);
                            tmp.setMeasurementUnits(measurement_units);
                            tmp.setWeight(weight);
                            tmp.setWeightUnits(weight_units);
                            tmp.setItemVolume(item_volume);
                            tmp.setVolumeUnits(volume_units);
                            tmp.setProductSizeTier(product_size_tier);
                            tmp.setAverageQuantityOnHand(average_quantity_on_hand);
                            tmp.setAverageQuantityPendingRemoval(average_quantity_pending_removal);
                            tmp.setEstimatedTotalItemVolume(estimated_total_item_volume);
                            tmp.setMonthOfCharge(month_of_charge);
                            tmp.setStorageRate(storage_rate);
                            tmp.setCurrency(currency);
                            tmp.setEstimatedMonthlyStorageFee(estimated_monthly_storage_fee);
                            tmp.setDangerousGoodsStorageType(dangerous_goods_storage_type);
                            tmp.setEligibleForInventoryDiscount(eligible_for_inventory_discount);
                            tmp.setQualifiesForInventoryDiscount(qualifies_for_inventory_discount);
                            tmp.setTotalIncentiveFeeAmount(total_incentive_fee_amount);
                            tmp.setBreakdownIncentiveFeeAmount(breakdown_incentive_fee_amount);
                            tmp.setAverageQuantityCustomerOrders(average_quantity_customer_orders);

                            list.add(tmp);
                        }
                        lineNumber++;
                        // Process line by line.
                    }
                    tmpStorageFeeMonthService.saveBatch(list);
                } else {
                    //Handle content with binary data/other media types here.
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                log.error("处理月仓储费数据异常",e);
            } finally {
                if (closeThis != null) {
                    closeThis.close();
                }
            }
        }
    }
}
